﻿#include "wbasenode.h"
#include "wnodemanager.h"
#include "../maindrawscene.h"

#include <algorithm> // for std::sort

bool compareByScoreDesc(const tagMountPoint& a, const tagMountPoint& b) {
    return a.level > b.level;
}

WBaseNode::WBaseNode()
    : mParentNode(NULL),
      mNodeType(NODE_NULL),
      mDeviceID(-1),
      mNodeManager(NULL),
      mNodeOperState(NodeOperState::NORMAL),
      mNodeSignalState(NodeSignalState::NOSIGNAL),
      mWorkingMode(WorkingMode::MODE_EIDTING)
{

}

WBaseNode::WBaseNode(wxString pname)
    : mName(pname),
      mDeviceID(-1),
      mNodeType(NODE_NULL),
      mParentNode(NULL),
      mNodeManager(NULL),
      mNodeOperState(NodeOperState::NORMAL),
      mNodeSignalState(NodeSignalState::NOSIGNAL),
      mWorkingMode(WorkingMode::MODE_EIDTING)
{

}

WBaseNode::~WBaseNode()
{

}

/// 设置挂接点的显示位置
void WBaseNode::setPosition(wxRealPoint pos)
{
    mCenterPosition = pos;

    this->changeWorkingRect(this->getNodeManager()->getWorkingRect());
}

/// 得到指定方向上的所有挂载点
wxVector<tagMountPoint> WBaseNode::getMountPointByDir(int dir)
{
    wxVector<tagMountPoint> tmpMountPoints;

    std::map<wxString,tagMountPoint>::iterator iter = mMountPoints.begin();
    for(;iter != mMountPoints.end();++iter)
    {
        if((*iter).second.direction != (MountDirection)dir)
            continue;

        tmpMountPoints.push_back((*iter).second);
    }

    // 按照等级排序
    std::sort(tmpMountPoints.begin(), tmpMountPoints.end(), compareByScoreDesc);

    return tmpMountPoints;
}

/// 设置指定名称挂接点的角度
void WBaseNode::setMountPointAngle(wxString name,double angle)
{
    if(mMountPoints.empty() || name == "")
        return;

    std::map<wxString,tagMountPoint>::iterator iter = mMountPoints.find(name);
    if(iter != mMountPoints.end())
        (*iter).second.angle = angle;
}

/// 根据状态得到文字颜色
wxColour WBaseNode::getTextColourByState(void)
{
    assert(this != nullptr);  // 确保 this 有效

    wxColour decColour = wxColour(255,255,255,255);

    // 先判断操作条件
    switch(this->getOperState())
    {
    case NodeOperState::CHOSEN:            // 选中
        decColour = wxColour(165, 42, 42,255);
        break;
    case NodeOperState::LOCKED:            // 锁闭
        decColour = wxColour(0, 255, 0,255);
        break;
    default:
        break;
    }

    return decColour;
}

/// 根据状态得到颜色
wxColour WBaseNode::getColourByState(void)
{
    wxColour decColour = wxColour(255,255,255,255);

    // 先判断操作条件
    switch(this->getOperState())
    {
    case NodeOperState::CHOSEN:            // 选中
        decColour = wxColour(165, 42, 42,255);
        break;
    case NodeOperState::LOCKED:            // 锁闭

        if(this->getNodeType() == NodeType::NODE_SWITCH)
        {
            if(this->getSignalState() == NodeSignalState::CLEAR)
                return wxColour(0, 255, 0,255);
        }

        decColour = wxColour(0, 255, 0,255);
        break;
    default:
        break;
    }

    // 信号条件
    switch(this->getSignalState())
    {
    case NodeSignalState::OCCUPY:             // 占用
    {
        switch(this->getNodeType())
        {
        case NodeType::NODE_SWITCH:
            decColour = wxColour(255, 0, 0,255);
            break;
        case NodeType::NODE_SIGNAL:
            decColour = wxColour(255, 255, 255,255);
            break;
        default:
            break;
        }
    }
        break;
    case NodeSignalState::CLEAR:              // 蓝灯
    {
        switch(this->getNodeType())
        {
        case NodeType::NODE_SWITCH:
            decColour = wxColour(255, 255, 255,255);
            break;
        case NodeType::NODE_SIGNAL:
            decColour = wxColour(0, 0, 255,255);
            break;
        default:
            break;
        }
    }
        break;
    case NodeSignalState::NOSIGNAL:           // 没信号
    {
        decColour = wxColour(255, 255, 0,255);

        switch(this->getNodeType())
        {
        case NodeType::NODE_SWITCH:
            decColour = wxColour(255, 255, 0,255);
            break;
        case NodeType::NODE_SIGNAL:
            decColour = wxColour(0, 0, 255,255);
            break;
        default:
            break;
        }
    }
        break;
    default:
        break;
    }

    return decColour;
}

/// 重置结点状态
void WBaseNode::reset(void)
{
    mNodeOperState = NodeOperState::NORMAL;
}

/// 删除与关联结点有关的挂载点
bool WBaseNode::deleteMountPointByNode(WBaseNode* node)
{
    if(mMountPoints.empty() || node == NULL)
        return false;

    std::map<wxString,tagMountPoint>::iterator iter = mMountPoints.begin();
    for(;iter != mMountPoints.end();++iter)
    {
        if((*iter).second.node == node)
        {
            mMountPoints.erase(iter);
            return true;
        }
    }

    return false;
}

/// 添加一个挂载点
bool WBaseNode::addMountPoint(wxString name,const tagMountPoint& point)
{
    if(isExistMountPoint(name)) return false;

    mMountPoints[name] = point;

    this->changeWorkingRect(this->getNodeManager()->getWorkingRect());

    return true;
}

/// 检测指定名称的挂载点是否存在
bool WBaseNode::isExistMountPoint(wxString name)
{
    std::map<wxString,tagMountPoint>::iterator iter = mMountPoints.find(name);
    if(iter != mMountPoints.end())
        return true;

    return false;
}

/// 得到指定名称的挂载点
tagMountPoint* WBaseNode::getMountPointByName(wxString name)
{
    std::map<wxString,tagMountPoint>::iterator iter = mMountPoints.find(name);
    if(iter != mMountPoints.end())
        return &(*iter).second;

    return NULL;
}

/// 得到关联结点的挂载点
tagMountPoint* WBaseNode::getMountPointByNode(WBaseNode* node)
{
    if(node == NULL || mMountPoints.empty())
        return NULL;

    std::map<wxString,tagMountPoint>::iterator iter = mMountPoints.begin();
    for(;iter != mMountPoints.end();++iter)
    {
        if((*iter).second.node == node)
            return &(*iter).second;
    }

    return NULL;
}

/// 更改挂载点的名称
bool WBaseNode::updateMountPointName(wxString oldname,wxString newname)
{
    if((oldname == "" || newname == "") || oldname == newname)
        return false;

    tagMountPoint *poldMountPoint = this->getMountPointByName(oldname);
    if(poldMountPoint == NULL)
        return false;

    tagMountPoint *pnewMountPoint = this->getMountPointByName(newname);
    if(pnewMountPoint != NULL)
        return false;

    poldMountPoint->name = newname;

    mMountPoints[newname] = *poldMountPoint;

    // 先清除老的
    this->deleteMountPoint(oldname);

    return true;
}

/// 删除指定名称的挂载点
bool WBaseNode::deleteMountPoint(wxString name)
{
    if(name == "" || mMountPoints.empty())
        return false;

    bool isOk = false;

    std::map<wxString,tagMountPoint>::iterator iter = mMountPoints.find(name);
    if(iter != mMountPoints.end())
    {
        mMountPoints.erase(iter);
        isOk = true;
    }

    return isOk;
}

/// 检查指定结点是否在当前结点的挂载点内
bool WBaseNode::isExistMountNode(WBaseNode* node,int dir,tagMountPoint* point)
{
    if(node == NULL || point == NULL) return false;

    if(dir == MountDirection::DIRECTION_NULL)
    {
        // Using find_if instead of manual iteration
        auto iter = std::find_if(mMountPoints.begin(), mMountPoints.end(),
                                 [node](const auto& pair) {
                                     return pair.second.node == node;
                                 });

        if(iter != mMountPoints.end()) {
            *point = iter->second;
            return true;
        }
        return false;
    }

    // Assuming getMountPointByDir now returns const&
    const wxVector<tagMountPoint>& pPoints = this->getMountPointByDir(dir);

    auto it = std::find_if(pPoints.begin(), pPoints.end(),
                           [node](const tagMountPoint& item) {
                               return item.node == node;
                           });

    if(it != pPoints.end()) {
        *point = *it;
        return true;
    }

    return false;
}

/// 工作区域改变
void WBaseNode::changeWorkingRect(wxRect workingrect)
{
    if(mMountPoints.empty()) return;

    this->setWorkingRect(workingrect);

    std::map<wxString,tagMountPoint>::iterator iter = mMountPoints.begin();
    for(;iter != mMountPoints.end();++iter)
    {
        if(this->getNodeType() == NodeType::NODE_SIGNAL)
        {
            (*iter).second.screenpos = wxRealPoint((workingrect.GetTopLeft().x+workingrect.GetWidth() * ((*iter).second.pos.x / 100.0f)),
                                                   (workingrect.GetTopLeft().y+workingrect.GetHeight() * ((*iter).second.pos.y / 100.0f)));
        }
        else
        {
            (*iter).second.screenpos = wxRealPoint((workingrect.GetTopLeft().x+workingrect.GetWidth() * (this->getPosition().x / 100.0f) + (*iter).second.pos.x),
                                                   (workingrect.GetTopLeft().y+workingrect.GetHeight() * (this->getPosition().y / 100.0f)) + (*iter).second.pos.y);
        }
    }
}

/// 绘制所有的挂载点
void WBaseNode::DrawMountPoints(maindrawscene *painter)
{
    if(mMountPoints.empty() ||
       this->getWorkingMode() != WorkingMode::MODE_EIDTING) return;

    std::map<wxString,tagMountPoint>::iterator iter = mMountPoints.begin();
    for(;iter != mMountPoints.end();++iter)
    {
        painter->DrawPoint((*iter).second.screenpos,
                           ((*iter).second.direction == DIRECTION_LEFT ? wxColour(0,255,0,255) :
                                                                         wxColour(255,255,0,255)),
                           4.0f);
    }
}

/// 绘制包围盒
void WBaseNode::DrawBoundingBox(maindrawscene *painter)
{
    if(this->getBoundingRect().empty() ||
       this->getWorkingMode() != WorkingMode::MODE_EIDTING) return;

    for(int i=0;i<this->getBoundingRect().size()-1;i++)
    {
        painter->DrawLine(this->getBoundingRect()[i],this->getBoundingRect()[i+1],
                1.0f,wxColour(255,255,255,255));
    }

    painter->DrawLine(this->getBoundingRect()[0],this->getBoundingRect()[this->getBoundingRect().size()-1],
            1.0f,wxColour(255,255,255,255));
}
